package com.zyh.scs.admin.utils.jd;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * desc:
 *
 * @author hwh
 */
public class SignatureUtil {

    static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.registerModule(new JavaTimeModule());
    }

    public static String genSrcData(TreeMap<String, Object> paramMap, List<String> unSignKeyList) {
        StringBuilder sb = new StringBuilder();

        for (final String iterator : unSignKeyList) {
            paramMap.remove(iterator);
        }

        Iterator<Map.Entry<String, Object>> iterator = paramMap.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, Object> result1 = iterator.next();
            final Object value = result1.getValue();
            if (value != null && !((String) value).trim().isEmpty()) {
                sb.append(result1.getKey()).append("=").append(value).append("&");
            }
        }

        String result2 = sb.toString();
        if (result2.endsWith("&")) {
            result2 = result2.substring(0, result2.length() - 1);
        }
        return result2;
    }

    public static String signStringx(Object object, List<String> unSignKeyList) throws IllegalArgumentException, IllegalAccessException {
        TreeMap map = objectToMap(object);
        return genSrcData(map, unSignKeyList);
    }

    public static String signString(Object object, List<String> unSignKeyList) {
        Map<String, Object> map = objectMapper.convertValue(object, new TypeReference<TreeMap<String, Object>>() {
        });
        unSignKeyList.forEach(map::remove);
        return map.entrySet().stream()
                .filter(e -> !ObjectUtils.isEmpty(e.getValue()))
                .map(e ->
                        {
                            final Object value = e.getValue();
                            if (value instanceof String v) {
                                return e.getKey() + "=" + v;
                            }
                            return e.getKey() + "=" + value.toString();
                        }
                )
                .collect(Collectors.joining("&"));
    }


    public static TreeMap<String, Object> objectToMap(Object object) throws IllegalArgumentException, IllegalAccessException {
        TreeMap map = new TreeMap();

        for (Class cls = object.getClass(); cls != Object.class; cls = cls.getSuperclass()) {
            Field[] fields = cls.getDeclaredFields();
            Field[] var7 = fields;
            int var6 = fields.length;

            for (int var5 = 0; var5 < var6; ++var5) {
                Field f = var7[var5];
                f.setAccessible(true);
                map.put(f.getName(), f.get(object));
            }
        }
        return map;
    }


    /**
     * 验证签名是否正确
     * @param s1
     * @param signData
     * @param rsaSignPubKey
     * @return
     */
    public static boolean verifySign(String s1, String signData, String rsaSignPubKey) {
        boolean flag;
        if(signData != null && signData.length()!= 0) {
            if(rsaSignPubKey != null && rsaSignPubKey.length() != 0) {
                try {
                    String s2 = ShaUtil.encrypt(s1, "SHA-256");

                    byte[] signByte = RsaCoder.decryptBASE64(signData);
                    byte[] decryptArr = RsaCoder.decryptByPublicKey(signByte, rsaSignPubKey);
                    String decryptStr = new String(decryptArr);
                    if(s2.equals(decryptStr)) {
                        flag = true;
                        return flag;
                    } else {
                        throw new RuntimeException("Signature verification failed.");
                    }
                } catch (Exception e) {
                    throw new RuntimeException("verify signature failed.", e);
                }
            } else {
                throw new IllegalArgumentException("Argument \'rsaSignPubKey\' is null or empty");
            }
        } else {
            throw new IllegalArgumentException("Argument \'signData\' is null or empty");
        }
    }
}
